/*
    SUSAN® - Sole of Unix Save ANything

      Copyright (C) 2011-2016 Skyatlas Co. LTD

   

   
*/

/*
 * Marco van Wieringen, March 2012
 */

#ifndef BAREOS_LIB_SCSI_LLI_H_
#define BAREOS_LIB_SCSI_LLI_H_ 1

/*
 * Device Inquiry Response
 */
typedef struct {
#if HAVE_BIG_ENDIAN
  uint8_t peripheralQualifier : 3;
  uint8_t periphrealDeviceType : 5;
  uint8_t RMB : 1;
  uint8_t res_bits_1 : 7;
#else
  uint8_t periphrealDeviceType : 5;
  uint8_t peripheralQualifier : 3;
  uint8_t res_bits_1 : 7;
  uint8_t RMB : 1;
#endif
  uint8_t Version[1];
#if HAVE_BIG_ENDIAN
  uint8_t obs_bits_1 : 2;
  uint8_t NORMACA : 1;
  uint8_t HISUP : 1;
  uint8_t responseDataFormat : 4;
#else
  uint8_t responseDataFormat : 4;
  uint8_t HISUP : 1;
  uint8_t NORMACA : 1;
  uint8_t obs_bits_1 : 2;
#endif
  uint8_t additionalLength[1];
#if HAVE_BIG_ENDIAN
  uint8_t SCCS : 1;
  uint8_t ACC : 1;
  uint8_t TPGS : 2;
  uint8_t threePC : 1;
  uint8_t res_bits_2 : 2;
  uint8_t protect : 1;
  uint8_t obs_bits_2 : 1;
  uint8_t ENCSERV : 1;
  uint8_t VS : 1;
  uint8_t MULTIP : 1;
  uint8_t MCHNGR : 1;
  uint8_t obs_bits_3 : 2;
  uint8_t ADDR16 : 1;
  uint8_t obs_bits_4 : 2;
  uint8_t WBUS16 : 1;
  uint8_t SYNC : 1;
  uint8_t obs_bits_5 : 2;
  uint8_t CMDQUE : 1;
  uint8_t VS2 : 1;
#else
  uint8_t protect : 1;
  uint8_t res_bits_2 : 2;
  uint8_t threePC : 1;
  uint8_t TPGS : 2;
  uint8_t ACC : 1;
  uint8_t SCCS : 1;
  uint8_t ADDR16 : 1;
  uint8_t obs_bits_3 : 2;
  uint8_t MCHNGR : 1;
  uint8_t MULTIP : 1;
  uint8_t VS : 1;
  uint8_t ENCSERV : 1;
  uint8_t obs_bits_2 : 1;
  uint8_t VS2 : 1;
  uint8_t CMDQUE : 1;
  uint8_t obs_bits_5 : 2;
  uint8_t SYNC : 1;
  uint8_t WBUS16 : 1;
  uint8_t obs_bits_4 : 2;
#endif
  uint8_t vendor[8];
  uint8_t productID[16];
  uint8_t productRev[4];
  uint8_t SN[7];
  uint8_t venderUnique[12];
#if HAVE_BIG_ENDIAN
  uint8_t res_bits_3 : 4;
  uint8_t CLOCKING : 2;
  uint8_t QAS : 1;
  uint8_t IUS : 1;
#else
  uint8_t IUS : 1;
  uint8_t QAS : 1;
  uint8_t CLOCKING : 2;
  uint8_t res_bits_3 : 4;
#endif
  uint8_t res_bits_4[1];
  uint8_t versionDescriptor[16];
  uint8_t res_bits_5[22];
  uint8_t copyright[1];
} SCSI_PAGE_INQ;

/*
 * Sense Data Response
 */
typedef struct {
#if HAVE_BIG_ENDIAN
  uint8_t valid : 1;
  uint8_t responseCode : 7;
#else
  uint8_t responseCode : 7;
  uint8_t valid : 1;
#endif
  uint8_t res_bits_1;
#if HAVE_BIG_ENDIAN
  uint8_t filemark : 1;
  uint8_t EOM : 1;
  uint8_t ILI : 1;
  uint8_t res_bits_2 : 1;
  uint8_t senseKey : 4;
#else
  uint8_t senseKey : 4;
  uint8_t res_bits_2 : 1;
  uint8_t ILI : 1;
  uint8_t EOM : 1;
  uint8_t filemark : 1;
#endif
  uint8_t information[4];
  uint8_t addSenseLen;
  uint8_t cmdSpecificInfo[4];
  uint8_t addSenseCode;
  uint8_t addSenseCodeQual;
  uint8_t fieldRepUnitCode;
#if HAVE_BIG_ENDIAN
  uint8_t sim : 3; /* system information message */
  uint8_t bpv : 1; /* bit pointer valid */
  uint8_t resvd2 : 2;
  uint8_t cd : 1; /* control/data */
  uint8_t SKSV : 1;
#else
  uint8_t SKSV : 1;
  uint8_t cd : 1; /* control/data */
  uint8_t resvd2 : 2;
  uint8_t bpv : 1; /* bit pointer valid */
  uint8_t sim : 3; /* system information message */
#endif
  uint8_t field[2]; /* field pointer */
  uint8_t addSenseData[109];
} SCSI_PAGE_SENSE;

bool RecvScsiCmdPage(int fd,
                     const char* device_name,
                     void* cdb,
                     unsigned int cdb_len,
                     void* cmd_page,
                     unsigned int cmd_page_len);
bool send_scsi_cmd_page(int fd,
                        const char* device_name,
                        void* cdb,
                        unsigned int cdb_len,
                        void* cmd_page,
                        unsigned int cmd_page_len);
bool CheckScsiAtEod(int fd);
#endif /* BAREOS_LIB_SCSI_LLI_H_ */
